home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Windows Expert
/
Windows Expert.iso
/
others
/
ole_101.zip
/
PATRON.ZIP
/
BLACKBOX.C
next >
Wrap
C/C++ Source or Header
|
1992-04-13
|
16KB
|
600 lines
/*
* BLACKBOX.C
*
* Code for a BlackBox window that will contain and OLE object.
*
* Copyright(c) Microsoft Corp. 1992 All Rights Reserved
*/
#include <windows.h>
#include <ole.h>
#include "oclient.h"
#include "patron.h"
#include "blackbox.h"
/*
* FileObjectDefaults
*
* Purpose:
* Fills a FILEOBJECT structure with defaults for a BlackBox window:
* wID, rc, and szName. dwSize is not affected. This is so
* HBlackBoxCreate can take a FILEOBJECT pointer for the initial
* values of these fields.
*
* Parameters:
* pFO LPFILEOBJECT to fill.
*
* Return Value:
* None
*/
void FAR PASCAL FileObjectDefaults(LPFILEOBJECT pFO)
{
pFO->wID=WIDGetNext(FALSE);
PRectGetNext(&pFO->rc, FALSE);
//Don't use a colon or backslash in the name. Some apps may strip it.
wsprintf(pFO->szName, "%s[%d]", (LPSTR)rgpsz[IDS_CLASSBLACKBOX], pFO->wID);
return;
}
/*
* HBlackBoxCreate
*
* Purpose:
* Constructor function for the black box window, simply calling
* CreateWindow and activating that window. Initial position, parentage,
* and pointers to an LPCLIENT and an LPOBJECT are given by the caller.
*
* Parameters:
* hWndParent HWND of the parent window
* pFO LPFILEOBJECT containing ID, rectangle, and name. If
* this is NULL this function calls FileObjectDefault to
* fill one.
* fShow BOOL TRUE to show and activate the window. FALSE
* creates it hidden.
* pObj LPOBJECT to associate with this window.
*
* Return Value:
* HWND Handle to the new window if successful, FALSE otherwise.
*/
HWND FAR PASCAL HBlackBoxCreate(HWND hWndParent, LPFILEOBJECT pFO,
BOOL fShow, LPOBJECT pObj)
{
OLESTATUS os;
FILEOBJECT fo;
HWND hWnd=NULL;
HANDLE hInst;
DWORD dwStyle;
if (NULL==hWndParent || NULL==pObj)
return NULL;
if (NULL==pFO)
{
pFO=&fo;
FileObjectDefaults(pFO);
}
hInst=GetWindowWord(hWndParent, GWW_HINSTANCE);
//Set the visible bit if so requested.
dwStyle=WS_BORDER | WS_CHILD | WS_CLIPSIBLINGS | WS_THICKFRAME;
dwStyle |= (fShow) ? WS_VISIBLE : 0L;
//Create the window initially hidden.
hWnd=CreateWindow(rgpsz[IDS_CLASSBLACKBOX], pFO->szName, dwStyle,
pFO->rc.left, pFO->rc.top,
pFO->rc.right-pFO->rc.left, pFO->rc.bottom-pFO->rc.top,
hWndParent, pFO->wID, hInst, (LPVOID)pObj);
//Activate this window.
if (NULL!=hWnd && fShow)
{
BringWindowToTop(hWnd);
SendMessage(hWnd, WM_NCACTIVATE, TRUE, 0L);
FDirtySet(TRUE);
}
//Delete the object we were given if we fail.
if (NULL==hWnd)
{
//Cleanup the object we created.
os=OleDelete(pObj->pObj);
OsError(os, pObj->pDoc, pObj, TRUE);
//Cleanup what was given to us.
PObjectFree(pObj->pDoc, pObj);
}
return hWnd;
}
/*
* BlackBoxWndProc
*
* Purpose:
* Window class procedure for the BlackBox window. Standard callback.
*
* Parameters:
* Standard.
*
* Return Value:
* Standard.
*/
long FAR PASCAL BlackBoxWndProc(HWND hWnd, UINT iMsg, UINT wParam, LONG lParam)
{
LPCREATESTRUCT pCreate;
PBLACKBOX pBL;
HANDLE hMem;
HWND hWndParent;
HDC hDC;
PAINTSTRUCT ps;
RECT rc;
WORD cx, cy;
hWndParent=GetParent(hWnd);
pBL=(PBLACKBOX)GetWindowWord(hWnd, GWW_BLACKBOXHMEM);
if (WM_USER <= iMsg)
return LBlackBoxUserMessage(hWnd, iMsg, wParam, lParam, pBL);
switch (iMsg)
{
case WM_NCCREATE:
hMem=LocalAlloc(LPTR, CBBLACKBOX);
if (NULL==hMem)
return 0L;
SetWindowWord(hWnd, GWW_BLACKBOXHMEM, (HANDLE)hMem);
//Must use DefWindowProc to correctly set window text.
return (DefWindowProc(hWnd, iMsg, wParam, lParam));
case WM_CREATE:
pCreate=(LPCREATESTRUCT)lParam;
pBL->pObj=(LPOBJECT)pCreate->lpCreateParams;
//Initialize this window's OBJECT structure
if (NULL==PObjectInitialize(pBL->pObj, pBL->pObj->pDoc))
{
/*
* Prevent WM_NCDESTROY from freeing structure. Let
* HBlackBoxCreate do it instead.
*/
pBL->pObj=NULL;
return -1L;
}
//Store our window handle in user-defined data space.
pBL->pObj->hData=hWnd;
pBL->fDrag=FALSE;
return 1L;
case WM_NCDESTROY:
if (NULL==pBL)
break;
if (NULL!=pBL->pObj);
PObjectFree(pBL->pObj->pDoc, pBL->pObj);
if (NULL!=pBL)
LocalFree((HANDLE)pBL);
break;
case WM_NCACTIVATE:
if (1==wParam)
{
//Notify the parent that we've been activated.
wParam=GetWindowWord(hWnd, GWW_ID);
lParam=MAKELONG(hWnd, BBN_ACTIVATED);
SendMessage(hWndParent, WM_COMMAND, wParam, lParam);
}
//Must do this to affect activation properly.
return (DefWindowProc(hWnd, iMsg, wParam, lParam));
case WM_SIZE:
//Inform the object that we changed size.
if (pBL->fUserResize)
{
/*
* Get the screen coordinates for the *client* area of
* this rectangle for passing to OleSetBounds through
* FObjectRectSet.
*/
GetWindowRect(hWnd, &rc);
//Subtract the borders.
cx=GetSystemMetrics(SM_CXFRAME);
cy=GetSystemMetrics(SM_CYFRAME);
InflateRect(&rc, -(int)cx, -(int)cy);
FObjectRectSet(pBL->pObj->pDoc, pBL->pObj, &rc, MM_TEXT);
pBL->fUserResize=FALSE;
wParam=GetWindowWord(hWnd, GWW_ID);
lParam=MAKELONG(hWnd, BBN_SIZED);
SendMessage(hWndParent, WM_COMMAND, wParam, lParam);
}
break;
case WM_PAINT:
hDC=BeginPaint(hWnd, &ps);
//Draw the object and show it as opened if it happens to be.
GetClientRect(hWnd, &rc);
FObjectPaint(hDC, &rc, pBL->pObj);
EndPaint(hWnd, &ps);
break;
case WM_NCLBUTTONDBLCLK:
//Go execute the primary verb.
SendMessage(hWnd, BBM_VERBEXECUTE, 0, 0L);
return (DefWindowProc(hWnd, iMsg, wParam, lParam));
case WM_NCHITTEST:
/*
* Make the whole client area act like a caption bar, but do
* not interfere with the sizing borders.
*/
lParam=DefWindowProc(hWnd, iMsg, wParam, lParam);
if ((LONG)HTCLIENT==lParam)
lParam=(LONG)HTCAPTION;
return lParam;
case WM_NCLBUTTONDOWN:
//Activate this window. WM_NCACTIVATE takes care of deactivating.
BringWindowToTop(hWnd);
SendMessage(hWnd, WM_NCACTIVATE, 1, 0L);
return (DefWindowProc(hWnd, iMsg, wParam, lParam));
case WM_SYSCOMMAND:
if (SC_SIZE==(wParam & 0xfff0))
{
//Indicate that next WM_SIZE was user-initiated.
pBL->fUserResize=TRUE;
}
return (DefWindowProc(hWnd, iMsg, wParam, lParam));
default:
return (DefWindowProc(hWnd, iMsg, wParam, lParam));
}
return 0L;
}
/*
* LBlackBoxUserMessage
*
* Purpose:
* Handles all window-specific messages WM_USER and greater,
* for the BlackBox window:
*
*
* Parameters:
* hWnd HWND of the BlackBox window.
* iMsg WORD message to process.
* wParam WORD parameter of the message.
* lParam LONG parameter of the message.
* pBL PBLACKBOX to the window's extra data structure.
*
* Return Value:
* DWORD Value to return from the window procedure
* that recieved the message.
*/
DWORD PASCAL LBlackBoxUserMessage(HWND hWnd, WORD iMsg, WORD wParam,
LONG lParam, PBLACKBOX pBL)
{
DWORD dwRet=0L;
HWND hWndParent;
LPRECT pRect;
RECT rc;
OLESTATUS os;
if (NULL==pBL)
return 0L;
hWndParent=GetParent(hWnd);
switch (iMsg)
{
case BBM_RECTSET:
/*
* lParam points to a RECT structure containing the new
* coordinates for the window in terms of the parent's
* client area, as we store in the files for this application.
*/
if ((LONG)NULL==lParam)
break;
pRect=(LPRECT)lParam;
AdjustWindowRect(pRect, WS_BORDER | WS_THICKFRAME, FALSE);
SetWindowPos(hWnd, NULL, pRect->left, pRect->top,
pRect->right-pRect->left,
pRect->bottom-pRect->top, SWP_NOZORDER);
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
dwRet=1L;
break;
case BBM_RECTGET:
/*
* lParam points to an LPRECT to fill with the coordinates
* of the window in terms of the parent's client area.
*/
if ((LONG)NULL==lParam)
break;
PRectWindowGet(hWnd, (LPRECT)lParam, hWndParent);
dwRet=1L;
break;
case BBM_POBJECTGET:
return (DWORD)pBL->pObj;
case BBM_OBJECTNOTIFY:
if (OLE_RENAMED==wParam)
{
PObjectInitialize(pBL->pObj, pBL->pObj->pDoc);
break;
}
if (OLE_SAVED==wParam || OLE_CHANGED==wParam)
{
//Get the size of the object we created and scale the new window to fit.
if (FObjectRectGet(pBL->pObj, &rc, MM_TEXT))
{
if (!pBL->fUserResize)
{
AdjustWindowRect(&rc, WS_BORDER | WS_THICKFRAME, FALSE);
SetWindowPos(hWnd, NULL, 0, 0, rc.right-rc.left,
rc.bottom-rc.top, SWP_NOMOVE | SWP_NOZORDER);
}
wParam=GetWindowWord(hWnd, GWW_ID);
lParam=MAKELONG(hWnd, BBN_CHANGED);
SendMessage(hWndParent, WM_COMMAND, wParam, lParam);
}
}
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
break;
case BBM_VERBEXECUTE:
/*
* The original OLE documentation states that OleSetHostNames
* should be called the first time the object is activated.
* OleSetHostNames simply sets names with OLECLI that it passes
* to a server's DocSetHostNames method when the object is
* opened. You don't really *have* to call OleSetHostNames
* here as long as you call it once before opening the object.
*
* We specifically do it within PObjectAllocate, which only
* may be slightly inefficient if we never activate the object,
* but it eliminates tracking whether or not we've been activated
* yet.
*/
GetClientRect(hWnd, &rc);
/*
* Check if the server is busy. You want to check now because
* you could call FOLEReleaseWait and then continue in
* OleActivate. Here we simply notify the user and exit.
*/
os=OleQueryReleaseStatus(pBL->pObj->pObj);
os=OsError(os, pBL->pObj->pDoc, pBL->pObj, TRUE);
if (OLE_OK!=os)
break;
//wParam holds the verb, starting at 0.
os=OleActivate(pBL->pObj->pObj, wParam, TRUE, TRUE, hWndParent, &rc);
if (OLE_OK==OsError(os, pBL->pObj->pDoc, pBL->pObj, TRUE))
{
//Force a repaint to insure that the window shows the open state.
pBL->pObj->fOpen=TRUE;
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
}
break;
default:
break;
}
return dwRet;
}
/*
* PRectWindowGet
*
* Purpose:
* Fills a rectangle with the coordinates of the given child window
* in terms of the CLIENT area of the parent window.
*
* Parameters:
* hWnd HWND of the window to get the rectangle for.
* pRect LPRECT to where to store the dimensions.
* hWndParent HWND of the parent window whose client area concerns us.
*
* Return Value:
* LPRECT Same as pRect passed.
*/
LPRECT FAR PASCAL PRectWindowGet(HWND hWnd, LPRECT pRect, HWND hWndParent)
{
POINT pt;
if ((LPRECT)NULL==pRect)
return pRect;
GetWindowRect(hWnd, pRect);
/*
* Note, I use the POINT variable to make it clear what is going on
* instead of trying to be utterly efficient in a rarely used function.
*/
pt.x=pRect->left;
pt.y=pRect->top;
ScreenToClient(hWndParent, &pt);
pRect->left=pt.x;
pRect->top=pt.y;
pt.x=pRect->right;
pt.y=pRect->bottom;
ScreenToClient(hWndParent, &pt);
pRect->right=pt.x;
pRect->bottom=pt.y;
return pRect;
}
/*
* WIDGetNext
*
* Purpose:
* Returns the next ID value to use in creating a BLACKBOX window.
* This function simply maintains a static counter.
*
* Parameters:
* fReset BOOL TRUE forces WIDGetNext to reset the ID to 1000,
* And 1000 is returned.
*
* Return Value:
* WORD Next ID value.
*/
WORD FAR PASCAL WIDGetNext(BOOL fReset)
{
static WORD wID=999;
if (fReset)
{
wID=1000;
return wID;
}
return ++wID;
}
/*
* PRectGetNext
*
* Purpose:
* Fills a RECT structure with the location and suggested size for
* a new BlackBox window. Prior to OLE, all windows are of the same
* size, but once we paste OLE objects, we must use the size in which
* they come.
*
* Parameters:
* pRect LPRECT in which to store the new coordinates.
* fReset BOOL TRUE to reset the coordinates to defaults.
* pRect is filled with these new defaults.
*
* Return Value:
* LPRECT Same as pRect passed in. NULL if pRect is NULL.
*/
LPRECT FAR PASCAL PRectGetNext(LPRECT pRect, BOOL fReset)
{
static WORD x=0, y=0;
static WORD cx=150, cy=150;
if (fReset)
{
x=0;
y=0;
cx=150;
cy=150;
if ((LPRECT)NULL!=pRect)
SetRect(pRect, x, y, x+cx, x+cy);
return pRect;
}
if ((LPRECT)NULL==pRect)
return (LPRECT)NULL;
SetRect(pRect, x, y, x+cx, y+cy);
x+=10;
if (x > 200)
x=0;
y+=10;
if (y > 150)
y=0;
cx=150;
cy=150;
return pRect;
}